#pragma once

#include "JsiDomDeclarationNode.h"

#include "NodeProp.h"

#include <memory>
#include <string>

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdocumentation"

#include "include/core/SkBlurTypes.h"
#include "include/core/SkMaskFilter.h"

#pragma clang diagnostic pop

namespace RNSkia {
class JsiBlurMaskNode : public JsiDomDeclarationNode, public JsiDomNodeCtor<JsiBlurMaskNode> {
public:
    explicit JsiBlurMaskNode(std::shared_ptr<RNSkPlatformContext> context)
        : JsiDomDeclarationNode(context, "skBlurMaskFilter", DeclarationType::MaskFilter)
    {}

    void decorate(DeclarationContext *context) override
    {
        bool respectCTM = _respectCTM->isSet() ? _respectCTM->value().getAsBool() : true;
        SkBlurStyle style = SkBlurStyle::kNormal_SkBlurStyle;
        if (_style->isSet()) {
            style = getBlurStyleFromString(_style->value().getAsString());
        }

        auto filter = SkMaskFilter::MakeBlur(style, _blur->value().getAsNumber(), respectCTM);

        // Set the mask filter
        context->getMaskFilters()->push(filter);
    }

protected:
    void defineProperties(NodePropsContainer *container) override
    {
        JsiDomDeclarationNode::defineProperties(container);

        _style = container->defineProperty<NodeProp>("style");
        _respectCTM = container->defineProperty<NodeProp>("respectCTM");
        _blur = container->defineProperty<NodeProp>("blur");

        _blur->require();
    }

private:
    SkBlurStyle getBlurStyleFromString(const std::string &value)
    {
        if (value == "normal") {
            return SkBlurStyle::kNormal_SkBlurStyle;
        } else if (value == "solid") {
            return SkBlurStyle::kSolid_SkBlurStyle;
        } else if (value == "outer") {
            return SkBlurStyle::kOuter_SkBlurStyle;
        } else if (value == "inner") {
            return SkBlurStyle::kInner_SkBlurStyle;
        }
        getContext()->raiseError(std::runtime_error("The value \"" + value + "\" is not " + "a valid blur style."));
        return SkBlurStyle::kNormal_SkBlurStyle;
    }

    NodeProp *_style;
    NodeProp *_respectCTM;
    NodeProp *_blur;
};
} // namespace RNSkia
